package main

import (
	"context"
	"errors"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"go.uber.org/zap"

	"k8soperation/global"
	"k8soperation/initialize"
)

func main() {
	// 1) 初始化配置与日志
	if err := initialize.SetupSetting(); err != nil {
		log.Fatalf("SetupSetting err: %v", err)
	}
	if err := initialize.SetupLogger(); err != nil {
		log.Fatalf("SetupLogger err: %v", err)
	}
	// 程序退出前刷盘日志
	defer func() { _ = global.Logger.Sync() }()

	// 2) 初始化数据库（按需：失败是否退出取决于你的业务）
	if err := initialize.SetupDB(); err != nil {
		global.Logger.Error("SetupDB err", zap.Error(err))
	}

	// 3) 构建 HTTP Server
	engine := initialize.NewEngine()

	// 关停超时：可配置，默认 5s
	shutdownTimeout := time.Duration(global.ServerSetting.ShutdownTimeout) * time.Second
	if shutdownTimeout <= 0 {
		shutdownTimeout = 5 * time.Second
	}

	// 创建并配置HTTP服务器实例
	server := &http.Server{
		Addr:              ":" + global.ServerSetting.Port, // 服务器监听地址，使用全局配置中的端口号
		Handler:           engine,                          // 服务器使用的路由引擎
		ReadHeaderTimeout: 5 * time.Second,                 // 防 slowloris，生产强烈建议
		ReadTimeout:       time.Duration(global.ServerSetting.ReadTimeout) * time.Second,
		WriteTimeout:      time.Duration(global.ServerSetting.WriteTimeout) * time.Second,
		IdleTimeout:       time.Duration(global.ServerSetting.IdleTimeout) * time.Second,
		MaxHeaderBytes:    1 << 20,                   // 1MB，设置header最大长度，防止DDOS
		ErrorLog:          global.Logger.StdLogger(), // 将标准库 http.Server 的内部错误输出接到 zap，便于统一日志落盘
	}

	// 关停回调：在关闭监听器后、等待连接清理前触发
	server.RegisterOnShutdown(func() {
		// 在这里做收尾：停止后台 worker、flush 指标等
		// 统一在回调里关闭 DB，避免遗漏
		if global.SQLDB != nil {
			_ = global.SQLDB.Close()
		}
	})

	// 4) 启动 HTTP 服务（前台不阻塞）
	go func() {
		global.Logger.Info("http server starting", zap.String("addr", server.Addr))
		if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			global.Logger.Error("http server error", zap.Error(err))
		}
	}()

	// 5) 监听退出信号（Ctrl+C / kill）
	stopCtx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
	defer stop() // 解除订阅，避免泄漏

	<-stopCtx.Done() // 阻塞直到收到退出信号
	global.Logger.Info("server shutting down...")

	// 6) 优雅关闭：给在途请求一个收尾时间窗口
	ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
	defer cancel()

	if err := server.Shutdown(ctx); err != nil {
		// 若超时/取消：err 可能是 context.DeadlineExceeded 或 context.Canceled
		global.Logger.Error("server shutdown error", zap.Error(err), zap.Duration("timeout", shutdownTimeout))
	} else {
		global.Logger.Info("server exited gracefully", zap.Duration("timeout", shutdownTimeout))
	}
}
